{ "cells": [ { "cell_type": "markdown", "id": "dd3d8d19", "metadata": {}, "source": [ "# LOv rewriting rules in Perceval\n", "\n", "The aim of this notebook is to rewrite a circuit using rewriting rules based on the article: *LOv-Calculus: A Graphical Language for Linear Optical Quantum Circuits*.\n", "\n", "We show how to use these rewriting rules to generate unique triangular normal forms." ] }, { "cell_type": "code", "execution_count": 1, "id": "96bdb88a", "metadata": {}, "outputs": [], "source": [ "import perceval as pcvl\n", "from perceval.utils.algorithms.optimize import optimize\n", "from perceval.utils.algorithms.norm import frobenius\n", "import random\n", "\n", "from perceval.rendering.circuit import DisplayConfig, SymbSkin\n", "DisplayConfig.select_skin(SymbSkin)" ] }, { "cell_type": "markdown", "id": "ba837e96", "metadata": {}, "source": [ "This is the first rewrite rule used in this noteobok. It is the rule 37 in the article." ] }, { "cell_type": "markdown", "id": "09923a89", "metadata": {}, "source": [ "![rewrite37](../_static/img/rewrite37.png)" ] }, { "cell_type": "code", "execution_count": 2, "id": "ede320ce", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "PATTERN1\n", "\n", "\n", "Φ=phi0\n", "\n", "\n", "Θ=theta1\n", "\n", "Rx\n", "\n", "\n", "Φ=phi2\n", "\n", "\n", "Φ=phi1\n", "\n", "\n", "Θ=theta2\n", "\n", "Rx\n", "\n", "\n", "Θ=theta3\n", "\n", "Rx\n", "\n", "\n", "\n", "\n", "0\n", "1\n", "2\n", "0\n", "1\n", "2\n", "" ], "text/plain": [ "" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pattern1=pcvl.Circuit(3, name=\"pattern1\")//(0,pcvl.PS(pcvl.P(\"phi0\")))//(0,pcvl.BS(theta=pcvl.P(\"theta1\")))//(0,pcvl.PS(pcvl.P(\"phi2\")))//(1,pcvl.PS(pcvl.P(\"phi1\")))//(1,pcvl.BS(theta=pcvl.P(\"theta2\")))//(0,pcvl.BS(theta=pcvl.P(\"theta3\")))\n", "pattern1._color = \"lightgreen\"\n", "pcvl.pdisplay(pcvl.Circuit(3).add(0,pattern1,False), recursive=True)" ] }, { "cell_type": "code", "execution_count": 3, "id": "1e1ee73a", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "REWRITE\n", "\n", "\n", "Φ=beta2\n", "\n", "\n", "Φ=beta1\n", "\n", "\n", "Θ=alpha1\n", "\n", "Rx\n", "\n", "\n", "Θ=alpha2\n", "\n", "Rx\n", "\n", "\n", "Φ=beta3\n", "\n", "\n", "Θ=alpha3\n", "\n", "Rx\n", "\n", "\n", "Φ=beta4\n", "\n", "\n", "Φ=beta5\n", "\n", "\n", "Φ=beta6\n", "\n", "\n", "\n", "\n", "0\n", "1\n", "2\n", "0\n", "1\n", "2\n", "" ], "text/plain": [ "" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rewrite1=pcvl.Circuit(3, name=\"rewrite\")//(0,pcvl.PS(pcvl.P(\"beta2\")))//(1,pcvl.PS(pcvl.P(\"beta1\")))//(1,pcvl.BS(theta=pcvl.P(\"alpha1\")))//(0,pcvl.BS(theta=pcvl.P(\"alpha2\")))//(1,pcvl.PS(pcvl.P(\"beta3\")))//(1,pcvl.BS(theta=pcvl.P(\"alpha3\")))//(0,pcvl.PS(pcvl.P(\"beta4\")))//(1,pcvl.PS(pcvl.P(\"beta5\")))//(2,pcvl.PS(pcvl.P(\"beta6\")))\n", "rewrite1._color = \"lightgreen\"\n", "pcvl.pdisplay(pcvl.Circuit(3).add(0,rewrite1,False), recursive=True)" ] }, { "cell_type": "markdown", "id": "d4197839", "metadata": {}, "source": [ "Let us implement now the rule number 1." ] }, { "cell_type": "markdown", "id": "171cff3a", "metadata": {}, "source": [ "![rewrite1](../_static/img/rewrite1.png)" ] }, { "cell_type": "code", "execution_count": 4, "id": "5468fdb9", "metadata": {}, "outputs": [], "source": [ "pattern2=pcvl.Circuit(1, name=\"pattern2\")//pcvl.PS(pcvl.P(\"phi1\"))//pcvl.PS(pcvl.P(\"phi2\"))\n", "rewrite2=pcvl.Circuit(1, name=\"rewrite2\")//pcvl.PS(pcvl.P(\"phi\"))" ] }, { "cell_type": "code", "execution_count": 5, "id": "e428775f", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "PATTERN2\n", "\n", "\n", "Φ=phi1\n", "\n", "\n", "Φ=phi2\n", "\n", "0\n", "0\n", "" ], "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pcvl.pdisplay(pcvl.Circuit(1).add(0,pattern2,False), recursive=True)" ] }, { "cell_type": "code", "execution_count": 6, "id": "e2bdd9f4", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "REWRITE2\n", "\n", "\n", "Φ=phi\n", "\n", "0\n", "0\n", "" ], "text/plain": [ "" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pcvl.pdisplay(pcvl.Circuit(1).add(0,rewrite2,False), recursive=True)" ] }, { "cell_type": "markdown", "id": "7d547376", "metadata": {}, "source": [ "In fact, this rule has been directly implemented in Perceval, with the call of `simplify`." ] }, { "cell_type": "code", "execution_count": 7, "id": "49074c57", "metadata": {}, "outputs": [], "source": [ "from perceval.utils.algorithms.simplification import simplify" ] }, { "cell_type": "markdown", "id": "6ceae57c", "metadata": {}, "source": [ "The third rule used in this notebook is the following one:" ] }, { "cell_type": "markdown", "id": "246fc6ce", "metadata": {}, "source": [ "![rewrite33](../_static/img/rewrite33.png)" ] }, { "cell_type": "code", "execution_count": 8, "id": "d056ab6c", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "PATTERN3\n", "\n", "\n", "Φ=phip\n", "\n", "\n", "Θ=theta\n", "\n", "Rx\n", "\n", "\n", "0\n", "1\n", "0\n", "1\n", "" ], "text/plain": [ "" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pattern3=pcvl.Circuit(2, name=\"pattern3\")//(1,pcvl.PS(pcvl.P(\"phip\")))//(0,pcvl.BS(theta=pcvl.P(\"theta\")))\n", "pattern3._color = \"pink\"\n", "pcvl.pdisplay(pcvl.Circuit(2).add(0,pattern3,False), recursive=True)" ] }, { "cell_type": "code", "execution_count": 9, "id": "6ef8057d", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "REWRITE3\n", "\n", "\n", "Φ=phi1\n", "\n", "\n", "Θ=theta\n", "\n", "Rx\n", "\n", "\n", "Φ=phi2\n", "\n", "\n", "Φ=phi3\n", "\n", "\n", "0\n", "1\n", "0\n", "1\n", "" ], "text/plain": [ "" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rewrite3=pcvl.Circuit(2, name=\"rewrite3\")//(0,pcvl.PS(pcvl.P(\"phi1\")))//(0,pcvl.BS(theta=pcvl.P(\"theta\")))//(0,pcvl.PS(pcvl.P(\"phi2\")))//(1,pcvl.PS(pcvl.P(\"phi3\")))\n", "rewrite3._color = \"pink\"\n", "pcvl.pdisplay(pcvl.Circuit(2).add(0,rewrite3,False), recursive=True)" ] }, { "cell_type": "markdown", "id": "6c7efe31", "metadata": {}, "source": [ "And the fourth rule is the rule 38 in the article." ] }, { "cell_type": "markdown", "id": "4cae9637", "metadata": {}, "source": [ "![rewrite38](../_static/img/rewrite38.png)" ] }, { "cell_type": "code", "execution_count": 10, "id": "597bc933", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "PATTERN4\n", "\n", "Θ=theta1\n", "\n", "Rx\n", "\n", "\n", "Φ=phi1\n", "\n", "\n", "Θ=theta2\n", "\n", "Rx\n", "\n", "\n", "0\n", "1\n", "0\n", "1\n", "" ], "text/plain": [ "" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "pattern4=pcvl.Circuit(2, name=\"pattern4\")//(0,pcvl.BS(theta=pcvl.P(\"theta1\")))//(0,pcvl.PS(pcvl.P(\"phi1\")))//(0,pcvl.BS(theta=pcvl.P(\"theta2\")))\n", "pattern4._color = \"orange\"\n", "pcvl.pdisplay(pcvl.Circuit(2).add(0,pattern4,False), recursive=True)" ] }, { "cell_type": "code", "execution_count": 11, "id": "1866e2c5", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "REWRITE4\n", "\n", "\n", "Φ=beta1\n", "\n", "\n", "Θ=alpha1\n", "\n", "Rx\n", "\n", "\n", "Φ=beta2\n", "\n", "\n", "Φ=beta3\n", "\n", "\n", "0\n", "1\n", "0\n", "1\n", "" ], "text/plain": [ "" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rewrite4=pcvl.Circuit(2, name=\"rewrite4\")//(0,pcvl.PS(pcvl.P(\"beta1\")))//(0,pcvl.BS(theta=pcvl.P(\"alpha1\")))//(0,pcvl.PS(pcvl.P(\"beta2\")))//(1,pcvl.PS(pcvl.P(\"beta3\")))\n", "rewrite4._color = \"orange\"\n", "pcvl.pdisplay(pcvl.Circuit(2).add(0,rewrite4,False), recursive=True)" ] }, { "cell_type": "code", "execution_count": 12, "id": "deafebff", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Φ=0.714717\n", "\n", "\n", "Θ=0.63083\n", "\n", "Rx\n", "\n", "\n", "Φ=0.406342\n", "\n", "\n", "Θ=0.425317\n", "\n", "Rx\n", "\n", "\n", "Φ=0.566162\n", "\n", "\n", "Θ=0.30391\n", "\n", "Rx\n", "\n", "\n", "Φ=0.554753\n", "\n", "\n", "Θ=0.903968\n", "\n", "Rx\n", "\n", "\n", "Φ=0.930902\n", "\n", "\n", "Θ=0.235299\n", "\n", "Rx\n", "\n", "\n", "Φ=0.858201\n", "\n", "Θ=0.336429\n", "\n", "Rx\n", "\n", "\n", "Φ=0.687349\n", "\n", "\n", "Θ=0.181449\n", "\n", "Rx\n", "\n", "\n", "Φ=0.400677\n", "\n", "\n", "Θ=0.271942\n", "\n", "Rx\n", "\n", "\n", "Φ=0.800875\n", "\n", "Θ=0.464146\n", "\n", "Rx\n", "\n", "\n", "Φ=0.368609\n", "\n", "\n", "Θ=0.198345\n", "\n", "Rx\n", "\n", "\n", "Φ=0.82193\n", "\n", "\n", "Θ=0.029511\n", "\n", "Rx\n", "\n", "\n", "Φ=0.459109\n", "\n", "Θ=0.101356\n", "\n", "Rx\n", "\n", "\n", "\n", "\n", "\n", "\n", "0\n", "1\n", "2\n", "3\n", "0\n", "1\n", "2\n", "3\n", "" ], "text/plain": [ "" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a=pcvl.Circuit.generic_interferometer(4, lambda idx:pcvl.Circuit(2)//pcvl.PS(phi=random.random())//pcvl.BS(theta=random.random()), depth=8, shape=\"rectangle\")\n", "pcvl.pdisplay(a, recursive=True, render_size=0.7)" ] }, { "cell_type": "markdown", "id": "f13dd7d7", "metadata": {}, "source": [ "## Normalizing Circuit" ] }, { "cell_type": "code", "execution_count": 13, "id": "0f5ee748", "metadata": {}, "outputs": [], "source": [ "import drawsvg as draw" ] }, { "cell_type": "code", "execution_count": 14, "id": "df109c0f", "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "\n", "Φ=3.759963\n", "\n", "\n", "Φ=3.750786\n", "\n", "\n", "Θ=12.052413\n", "\n", "Rx\n", "\n", "\n", "Θ=6.629598\n", "\n", "Rx\n", "\n", "\n", "Φ=1.127343\n", "\n", "\n", "Φ=4.318821\n", "\n", "\n", "Θ=4.433226\n", "\n", "Rx\n", "\n", "\n", "Φ=1.063861\n", "\n", "\n", "Φ=4.678118\n", "\n", "\n", "Θ=6.51914\n", "\n", "Rx\n", "\n", "Θ=5.359688\n", "\n", "Rx\n", "\n", "\n", "Φ=3.764987\n", "\n", "\n", "Φ=6.21441\n", "\n", "\n", "Θ=12.399699\n", "\n", "Rx\n", "\n", "\n", "Φ=0.89935\n", "\n", "\n", "Φ=3.124728\n", "\n", "\n", "\n", "\n", "\n", "\n", "0\n", "1\n", "2\n", "3\n", "0\n", "1\n", "2\n", "3\n", "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "matching pattern pattern3\n", "matching pattern pattern4\n", "matching pattern pattern1\n", "matching pattern pattern3\n", "matching pattern pattern4\n" ] } ], "source": [ "reverse = []\n", "direct=[]\n", "def draw_frame(a):\n", " if isinstance(a, pcvl.Circuit):\n", " d = pcvl.pdisplay(a, recursive=True, render_size=0.6)\n", " reverse.insert(0, d)\n", " direct.append(d)\n", " return d\n", " return a\n", "\n", "rules = [(pattern1, rewrite1, \"lightgreen\"), # (pattern2, rewrite2, \"lightblue\"),\n", " (pattern3, rewrite3, \"pink\"), (pattern4, rewrite4, \"orange\")]\n", "\n", "with draw.frame_animate_jupyter(draw_frame, delay=0.1) as anim:\n", " anim.draw_frame(a)\n", " while True:\n", " found = False\n", " for pattern, rewrite, color in rules:\n", " start_pos = 0\n", " while True:\n", " print(\"matching pattern\", pattern.name)\n", " matched = a.match(pattern, browse=True, pos=start_pos)\n", " if matched is None:\n", " break\n", " print(\"matching ok\", matched.v_map)\n", " idx = a.isolate(list(matched.pos_map.keys()), color=color)\n", " anim.draw_frame(a)\n", " for k, v in matched.v_map.items():\n", " pattern.param(k).set_value(v)\n", " v = pattern.compute_unitary(False)\n", " print(\"optimizing rewrite\",rewrite.name)\n", " res = optimize(rewrite, v, frobenius, sign=-1)\n", " print(\"found params with distance\", res.fun)\n", " subc = rewrite.copy()\n", " found = True\n", " a.replace(idx, subc, merge=False)\n", " anim.draw_frame(a)\n", " a.replace(idx, subc, merge=True)\n", " pattern.reset_parameters()\n", " rewrite.reset_parameters()\n", " a = simplify(a)\n", " anim.draw_frame(a)\n", " start_pos = idx\n", " if not found:\n", " break" ] }, { "cell_type": "markdown", "id": "954dfac2", "metadata": {}, "source": [ "This representation is exactly the normal form that we wanted to obtain !" ] }, { "cell_type": "markdown", "id": "c174aa4c", "metadata": {}, "source": [ "## Reference\n", "\n", "> A. Clément, N. Heurtel, S. Mansfield, S. Perdrix, B. Valiron. LOv-Calculus: A Graphical Language for Linear Optical Quantum Circuits, 47th International Symposium on Mathematical Foundations of Computer Science [MFCS](https://doi.org/10.4230/LIPIcs.MFCS.2022.35), 35:1--35:16 (2022)." ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 }